package com.ruoyi.gpt.controller;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.ruoyi.common.annotation.RateLimiter;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.validate.AddGroup;
import com.ruoyi.common.domain.ChatRequestBo;
import com.ruoyi.common.utils.redis.QueueUtils;
import com.ruoyi.core.domain.vo.ConfigVo;
import com.ruoyi.core.service.IConfigService;
import com.ruoyi.gpt.constants.QueueConstants;
import com.ruoyi.gpt.domain.WxMsg;
import com.ruoyi.gpt.domain.bo.WxMsgBo;
import com.ruoyi.gpt.domain.vo.GptUserVo;
import com.ruoyi.gpt.queue.RequestHandler;
import com.ruoyi.gpt.service.IGptUserService;
import com.ruoyi.gpt.service.IWxMsgService;
import lombok.RequiredArgsConstructor;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.Date;

@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/wx/chat")
public class ChatController extends BaseController {

    private final IWxMsgService wxMsgService;
    private final IGptUserService gptUserService;
    private final IConfigService  configService;

    @PostMapping("/ask")
    @Transactional
    @RateLimiter(count = 3, time = 60)
    public R<String> ask(@Validated(AddGroup.class) @RequestBody ChatRequestBo chatRequestBo){

        if(chatRequestBo.getQuestion().length() < 3){
            return R.fail("提问的问题不能小于3个字");
        }

        if(!chatRequestBo.getQuestion().endsWith("。") &&!chatRequestBo.getQuestion().endsWith("?")
            &&!chatRequestBo.getQuestion().endsWith("？")&&!chatRequestBo.getQuestion().endsWith("!")
            &&!chatRequestBo.getQuestion().endsWith("！"))
        {
            chatRequestBo.setQuestion(chatRequestBo.getQuestion() + "?");
        }
        Long userId = getUserId();
        GptUserVo gptUserVo = gptUserService.queryById(userId);
        // 此时可以根据用户是否还有有效时长，或者是否还有有效次数进行判断 是否发起请求
        if (ObjectUtil.isNull(gptUserVo)) {
            return R.fail("用户不存在");
        }
        // 判断当前用户登录的appid是否开启收费模式
        ConfigVo configVo = configService.queryByAppid(gptUserVo.getAppid());

        if("1".equals(configVo.getIsPay())){
            // 是收费模式 判断还有没有次数
            if (DateUtil.compare(gptUserVo.getGptEndTime(), new Date()) < 0 && gptUserVo.getGptRemaining() <= 0) {
                return R.fail(201,"使用时间已过期且剩余次数小于0");
            }
            // 收费模式 如果有时间，那就不用减次数
            if (DateUtil.compare(gptUserVo.getGptEndTime(), new Date()) > 0) {
                // 有时间，不用减次数
                chatRequestBo.setIsSubtract(0);
            }else{
                // 如果没有时间，每次调用扣除次数为1
                chatRequestBo.setIsSubtract(1);
            }

        }else{
            // 免费模式，这是每次调用扣除次数为0
            chatRequestBo.setIsSubtract(0);
        }

        // 保存消息并加入队列
        return saveMsgAndAddQueue(chatRequestBo,userId,gptUserVo);
    }

    /**
     * 保存消息并加入队列
     * @param chatRequestBo
     * @param userId
     * @param gptUserVo
     */
    private R<String> saveMsgAndAddQueue(ChatRequestBo chatRequestBo, Long userId, GptUserVo gptUserVo){

        // 发送消息
        WxMsgBo wxMsgBo = new WxMsgBo();
        wxMsgBo.setDetail(chatRequestBo.getQuestion());
        wxMsgBo.setInOut("1");
        wxMsgBo.setOpenid(gptUserVo.getOpenid());
        wxMsgBo.setAppid(gptUserVo.getAppid());
        wxMsgBo.setUserId(userId);
        wxMsgService.insertByBo(wxMsgBo);
        chatRequestBo.setAppid(wxMsgBo.getAppid());
        chatRequestBo.setOpenId(wxMsgBo.getOpenid());
        chatRequestBo.setUserId(userId);
        chatRequestBo.setCreateTime(new Date());
        chatRequestBo.setMsgId(wxMsgBo.getId());
        // 从apiKeys的队列中取出一个apiKey
        String apiKey = QueueUtils.getApiKey(QueueConstants.apiKeys);
        System.out.println("从队列中获取apiKey = " + apiKey);
        // 此处可以对apiKey进行判断，如果为空，那么就返回错误信息
        if(StrUtil.isBlank(apiKey)){
            return R.fail("apiKey为空");
        }
        // apiKey不为空，将其添加到请求中
        chatRequestBo.setApiKey(apiKey);
        // 将apiKey 再添加到apiKeys的队列中
        QueueUtils.addQueueObject(QueueConstants.apiKeys, apiKey);
        // 发起请求(将请求添加到阻塞队列中，等待被订阅者消费)
        QueueUtils.addQueueObject(QueueConstants.request, chatRequestBo);
        System.out.println("问题发送成功，等待队列订阅:");
        // 请求发送成功
        return R.ok("问题发送成功！请稍后",chatRequestBo.getMsgId()+"");
    }
}
